package com.icoolkj.api.wrap.core.handler;

import com.icoolkj.api.wrap.core.*;
import com.icoolkj.api.wrap.core.utils.WrapUtils;
import java.util.*;

/**
 * 改进的签名实现，解决List参数和嵌套对象的问题
 * @author icoolkj
 */
public class ImprovedWrapSigner implements WrapSigner {

    private final String appSecret;

    public ImprovedWrapSigner(String appSecret) {
        this.appSecret = appSecret;
    }

    @Override
    public <T extends WrapData> String signature(WrapRequest<T> data) {
        Map<String, Object> beanMap = convertToFlatMap(data.getData());
        
        // 添加标准字段
        beanMap.put(WrapUtils.APP_KEY, data.getAppKey());
        beanMap.put(WrapUtils.TIMESTAMP, data.getTimestamp());
        beanMap.put(WrapUtils.NONCE, data.getNonce());

        // 排序并构建签名字符串
        SortedMap<String, Object> sortedMap = new TreeMap<>(beanMap);
        StringBuilder plainText = new StringBuilder();
        for (Map.Entry<String, Object> entry : sortedMap.entrySet()) {
            plainText.append(entry.getKey()).append("=").append(formatValue(entry.getValue()));
            plainText.append("&");
        }
        
        if (plainText.length() > 0) {
            plainText.deleteCharAt(plainText.length() - 1);
        }
        
        Wrap wrap = HMACWrap.newSHA256Wrap(appSecret);
        return Base64.getEncoder().encodeToString(wrap.sign(plainText.toString()));
    }
    
    /**
     * 将嵌套对象转换为扁平化的Map，以便正确处理列表和嵌套对象
     * @param obj 待转换的对象
     * @return 扁平化的键值对Map
     */
    private Map<String, Object> convertToFlatMap(Object obj) {
        Map<String, Object> result = new HashMap<>();
        if (obj == null) {
            return result;
        }
        
        // 使用反射获取字段值并扁平化
        Class<?> clazz = obj.getClass();
        Arrays.stream(clazz.getDeclaredFields())
            .forEach(field -> {
                try {
                    field.setAccessible(true);
                    Object value = field.get(obj);
                    if (value != null) {
                        if (value instanceof List) {
                            // 处理列表类型
                            processList(result, field.getName(), (List<?>) value);
                        } else if (value instanceof Map) {
                            // 处理Map类型
                            processMap(result, field.getName(), (Map<?, ?>) value);
                        } else if (isComplexObject(value)) {
                            // 处理嵌套对象
                            Map<String, Object> nestedMap = convertToFlatMap(value);
                            for (Map.Entry<String, Object> entry : nestedMap.entrySet()) {
                                result.put(field.getName() + "." + entry.getKey(), entry.getValue());
                            }
                        } else {
                            // 处理基本类型
                            result.put(field.getName(), value);
                        }
                    }
                } catch (IllegalAccessException e) {
                    // 忽略访问异常
                }
            });
        
        return result;
    }
    
    /**
     * 处理List类型字段
     */
    private void processList(Map<String, Object> result, String fieldName, List<?> list) {
        for (int i = 0; i < list.size(); i++) {
            Object item = list.get(i);
            String key = fieldName + "[" + i + "]";
            
            if (isComplexObject(item)) {
                Map<String, Object> itemMap = convertToFlatMap(item);
                for (Map.Entry<String, Object> entry : itemMap.entrySet()) {
                    result.put(key + "." + entry.getKey(), entry.getValue());
                }
            } else {
                result.put(key, item);
            }
        }
    }
    
    /**
     * 处理Map类型字段
     */
    private void processMap(Map<String, Object> result, String fieldName, Map<?, ?> map) {
        for (Map.Entry<?, ?> entry : map.entrySet()) {
            String key = fieldName + "[" + entry.getKey() + "]";
            Object value = entry.getValue();
            
            if (isComplexObject(value)) {
                Map<String, Object> valueMap = convertToFlatMap(value);
                for (Map.Entry<String, Object> nestedEntry : valueMap.entrySet()) {
                    result.put(key + "." + nestedEntry.getKey(), nestedEntry.getValue());
                }
            } else {
                result.put(key, value);
            }
        }
    }
    
    /**
     * 判断是否为复杂对象（非基本类型）
     */
    private boolean isComplexObject(Object obj) {
        if (obj == null) {
            return false;
        }
        
        Class<?> clazz = obj.getClass();
        return !clazz.isPrimitive() && 
               !Number.class.isAssignableFrom(clazz) &&
               !String.class.equals(clazz) &&
               !Boolean.class.equals(clazz) &&
               !Date.class.equals(clazz) &&
               !clazz.isEnum();
    }
    
    /**
     * 格式化值为字符串，避免使用toString()导致的Java特定格式问题
     */
    private String formatValue(Object value) {
        if (value == null) {
            return "";
        }
        
        if (value instanceof Date) {
            return String.valueOf(((Date) value).getTime());
        } else if (value instanceof Calendar) {
            return String.valueOf(((Calendar) value).getTimeInMillis());
        } else if (value instanceof Boolean || 
                  value instanceof Number || 
                  value instanceof String ||
                  value.getClass().isEnum()) {
            return String.valueOf(value);
        }
        
        // 对于其他类型，使用简单的字符串表示，避免包含类名
        return String.valueOf(value);
    }
} 